// i.r(t), i.d(t, { default: () => ApiClient })
import Logger from "../utils/Logger"
import requestUtil, { RequestQueue } from "../utils/request.util"
import { ForbiddenException, UnauthorizedException, NotFoundException } from "../exception/system.exception"
class Organization {
  blurEnabled: boolean
  constructor(e) {
    this.blurEnabled = !1
    e && Object.assign(this, e)
  }
}

class User {
  memberships: any[]
  loggedIn: boolean
  flags: Set<string>
  id: string
  constructor(e?: any) {
    this.loggedIn = !1
    this.flags = new Set()
    this.memberships = []
    e && Object.assign(this, e)
  }
  getFlags(e = "") {
    if (this.memberships) {
      const e = funcUtil.getUrlParams("organization", "")
      for (const t of this.memberships) if ("" === e || t.organizationId === e) for (const e of t.flags) this.flags.add(e)
    }
    const t = new Set<string>()
    this.flags.forEach(i => {
      if (0 === i.indexOf(e)) {
        const n = i.replace(e, "")
        t.add(n)
      }
    })
    return t
  }
  hasFlag(e, t = "showcase") {
    return this.getFlags().has(`${t}/${e}`)
  }
  isOrganizationAdmin(e) {
    const t = this.getMembership(e)
    return !!(null == t ? void 0 : t.roles.includes("admin"))
  }
  getMembershipFlags(e) {
    const t = this.getMembership(e)
    return t ? t.flags : []
  }
  getMembership(e) {
    return this.memberships.find(t => t.organizationId === e)
  }
  hasMembershipFlag(e, t) {
    return this.getMembershipFlags(e).includes(t)
  }
  getMembershipFeature(e, t) {
    const i = this.getMembership(e)
    return (null == i ? void 0 : i.features[t]) || !1
  }
  hasMembership(e) {
    return this.memberships.some(t => t.organizationId === e)
  }
}
class Membership {
  features: any
  constructor(e) {
    this.features = {}
    e && Object.assign(this, e)
  }
}
const l = {
  parse: (e: string): number[] => {
    return e.split(".").reduce((e, t) => {
      const i = parseInt(t, 10)
      isNaN(i) || e.push(i)
      return e
    }, [])
  },
  compare: (e: string, i: string) => {
    const n = l.parse(e),
      s = l.parse(i)
    for (let e = 0; e < n.length; e++) {
      if (e >= s.length) return 1
      if (n[e] !== s[e]) return n[e] > s[e] ? 1 : -1
    }
    return s.length > n.length ? -1 : 0
  },
  gt: (e: string, t: string) => {
    return 1 === l.compare(e, t)
  },
  lt: (e: string, t: string) => {
    return -1 === l.compare(e, t)
  },
  eq: (e: string, t: string) => {
    return 0 === l.compare(e, t)
  }
}

const d = new Logger("user.serializers")
function u(e, t = "3.1") {
  const i = []
  for (let n of e) {
    const e = n.match(/^.*\-(\d+(?:\.\d+)*)$/)
    if (e && e[1]) {
      if (((n = n.replace(/-(\d+(?:\.\d+)*)$/, "")), l.lt(t, e[1]))) {
        d.debug(`Dropping feature flag ${n}, version >= ${e[1]} required`)
        continue
      }
      d.debug(`Enabled versioned feature flag ${n}`)
    }
    i.push(n)
  }
  return i
}
import browserUtil from "../utils/browser.util"

const g = new Logger("api")
const f = Object.freeze({ cacheClearTimeout: 60000 })
export class Api {
  apiQueue: RequestQueue
  storeQueue: RequestQueue
  prefetchedData: any
  baseUrl: string
  protected _configCache: any
  protected _userCache: any
  protected _organizationCache: any
  user: User
  constructor(e = new requestUtil.RequestQueue(), t = new requestUtil.RequestQueue(), i = {}, n = window.location.origin) {
    this.apiQueue = e
    this.storeQueue = t
    this.prefetchedData = i
    this.baseUrl = n
    this._configCache = {}
    this._userCache = {}
    this._organizationCache = {}
    setTimeout(() => {
      this.prefetchedData = {}
    }, f.cacheClearTimeout)
  }
  async init(e) {
    const t = [this.getUser().then(e => (this.user = e))]
    // e && t.push(this.getConfigs(e)),
    await Promise.all(t)
  }
  getOnStoreQueue(e: string, t: any = {}) {
    return this.get(e, t, this.storeQueue)
  }
  get(e: string, t: any = {}, i = this.apiQueue) {
    const { prefetchFrom } = t
    return prefetchFrom && this.prefetchedData[prefetchFrom]
      ? Promise.resolve(this.prefetchedData[prefetchFrom])
      : this.apiQueue.get(e, t).then(e => {
          if (null === e) throw Error("Data from get was null, possibly unparsable JSON")
          return e
        })
  }
  getImage(e: string, t: any): Promise<ArrayBuffer> {
    return this.getOnStoreQueue(e, Object.assign(Object.assign({}, t), { responseType: "image" }))
  }
  async getImageBitmap(e: string, width: number, height: number, n: any = {}) {
    if (browserUtil.canImageBitmap()) {
      const s = -1 !== e.indexOf("?")
      const newUrl = e + (s ? "&" : "?") + "imgopt=1"
      const image = await this.getOnStoreQueue(newUrl, Object.assign(Object.assign({}, n), { responseType: "blob" }))
      //@ts-ignore
      return createImageBitmap(image, 0, 0, width, height, {
        imageOrientation: n.flipY ? "flipY" : "none"
      })
    }
    return this.getImage(e, n)
  }
  async getConfigs(e: string, t?: boolean) {
    if (((e = e.toLowerCase()), !t && this._configCache[e])) return this._configCache[e]
    const i = t ? { responseType: "json" } : { responseType: "json", prefetchFrom: "config" }
    let n = {}
    const s = this.baseUrl + `/api/v1/config/${e}`
    try {
      n = await this.get(s, i)
    } catch (e) {
      g.warn(`Failed to load config from ${s}, ignoring`)
    }
    return t || (this._configCache[e] = n), n || {}
  }
  async getAppKey(e: string, t: string, i?: boolean) {
    if ("" === e || "" === t) return null
    const n = await this.getConfigs(e, i)
    return n.hasOwnProperty(t) ? n[t] : null
  }
  async getGeoIpLocation() {
    return funcUtil.localType()
  }
  async modelExists(e: string, t = { ignorePrefetch: !1 }) {
    if (e.length > 20) return Promise.resolve(!0)
    const { ignorePrefetch: i } = t
    if (!i && this.prefetchedData && this.prefetchedData.model) {
      const { model } = this.prefetchedData
      if (!model.sid && model.has_public_access_password) throw new UnauthorizedException("Model requires a password")
      return model.sid === e
    }
    const n = `${this.baseUrl}/api/v2/models/${e}/`
    const headers = { "Content-Type": "application/json" }
    return fetch(n, { method: "GET", headers }).then(async e => {
      if (e.ok) return !0
      if (403 === e.status) throw new ForbiddenException("Access denied (403)")
      throw new NotFoundException("Model not found (404)")
    })
  }
  async getUser(e?: string) {
    if (e && e in this._userCache) return this._userCache[e]
    // const t = `${this.baseUrl}/showcase/3.2/${e || "current.json"}`, //彭蔚
    const userJson = await this.get(`./json/user.json`, { responseType: "json" }).catch(e => {
      g.error(e)
    })
    let userData: User
    if (!userJson) userData = new User()
    const memberships = (userJson.memberships || []).map(
      t =>
        new Membership({
          userId: userJson.user_sid,
          organizationId: t.organization_sid,
          name: t.name,
          flags: u(t.flags || []),
          roles: t.roles || [],
          features: t.features || {}
        })
    )
    userData = new User({
      id: userJson.user_sid,
      firstName: userJson.first_name,
      lastName: userJson.last_name,
      email: userJson.email,
      loggedIn: userJson.is_authenticated,
      flags: new Set(u(userJson.flags)),
      memberships
    })
    userData.id && (this._userCache[userData.id] = userData)
    return userData
  }
}
import Module from "./Module"
import funcUtil from "../utils/func.util"

export default class ApiClient extends Module {
  api: Api
  constructor() {
    super()
    this.name = "api-client"
  }
  async init(config: any) {
    this.api = new Api(config.apiQueue, config.storeQueue, config.prefetchedData, config.baseUrl)
    await this.api.init(config.preloadConfig)
  }
  getApi() {
    return this.api
  }
}
